package cn.edu.njuit.lesson9heros.service.impl;


import cn.edu.njuit.lesson9heros.myioc.MyComponent;
import cn.edu.njuit.lesson9heros.pojo.Hero;
import cn.edu.njuit.lesson9heros.service.HeroService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONReader;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.stream.Collectors;

@MyComponent(name="heroService")
public class HeroServiceImpl implements HeroService {
    /**
     * 实例化英雄数据服务的时候，就进行英雄列表初始化工作。
     */
    public HeroServiceImpl(){
        //对象初始化时自动初始化英雄列表
        this.initHeros();
    }
    /**
     * 英雄库
     */
    private List<Hero> heros=new ArrayList<Hero>();
    /**
     * 初始化英雄库
     * @return
     */
    private void initHeros(){
        //定义英雄职业数组，根据hero_type值映射到对应的职业
        String [] types={"","战士","法师","坦克","刺客","射手","辅助"};
        //对应职业数组定义职业推荐的战斗位置
        String [] jobs={"","top","mid","top","jungle","adc","support"};
        //获得当前classPath，json文件在resource目录，编译后在class根目录中。
        String classPath=this.getClass().getClassLoader().getResource("").getPath();
        FileReader fileReader = null;
        try {
            fileReader = new FileReader(classPath+"herolist.json");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        JSONReader jsonReader = new JSONReader(fileReader);
        String heroString=jsonReader.readString();
        //读取json文件，转为JSONArray
        JSONArray jsonArray = JSON.parseArray(heroString);
        if(jsonArray.size()>0){
            //遍历数据，产生List<Hero>列表
            for(int i=0;i<jsonArray.size();i++){
                JSONObject heroJson=jsonArray.getJSONObject(i);
                Hero hero=new Hero();
                hero.setHeroId(heroJson.getInteger("ename"));
                hero.setHeroName(heroJson.getString("cname"));
                //解析出英雄对应的职业
                hero.setHeroType(types[heroJson.getInteger("hero_type")]);
                //根据职业设置对应的战斗位置
                hero.setRecommendedPosition(jobs[heroJson.getInteger("hero_type")]);
                this.heros.add(hero);
                //如果存在第二种职业，向英雄数组中再写入一次该英雄
                //此处有一种隐患，当英雄有3种、4种职业时，逻辑不适配。
                if(heroJson.containsKey("hero_type2")){
                    Hero heroCopy=new Hero();
                    heroCopy.setHeroId(heroJson.getInteger("ename"));
                    heroCopy.setHeroName(heroJson.getString("cname"));
                    heroCopy.setHeroType(types[heroJson.getInteger("hero_type2")]);
                    heroCopy.setRecommendedPosition(jobs[heroJson.getInteger("hero_type2")]);
                    //此处会导致列表中相同的英雄有因为职业不同，有2条数据，生成队伍时需要去重复，避免同一个英雄出现在两个位置中。
                    this.heros.add(heroCopy);
                }
            }
        }
        //System.out.println(JSON.toJSONString(heros));
    }

    @Override
    public Hero getHeroByName(String name) {
        Optional<Hero> heroOptional = this.heros.stream().filter(hero->{return hero.getHeroName().equals(name);}).findFirst();
        return heroOptional.get();
    }

    /**
     * 根据位置获得该位置全部英雄列表
     * @param position 推荐位置：top/mid/adc/support/jungle
     * @param exceptHeros 需要排除的英雄id，可选参数，不传递则不排除
     * @return
     */
    @Override
    public Hero getHeroByPosition(String position,Integer... exceptHeros) {
        //找到符合该位置的全部英雄
        List<Hero> positionList=this.heros.stream()
                .filter(hero->{
                    //位置匹配
                    boolean flag=hero.getRecommendedPosition().equals(position);
                    //如果有指定排除的英雄id输入，还需要过滤掉这些英雄
                    if(exceptHeros!=null && exceptHeros.length>0){
                        for (Integer exceptHero : exceptHeros) {
                            if(exceptHero.equals(hero.getHeroId())){
                                flag=false;
                                break;
                            }
                        }
                    }
                    return flag;
                })
                //这里进行去重复操作，避免同一个英雄有多个职业，出现在同一个战斗位置。例如英雄职业为坦克/战士两种的英雄，在上路列表中会出现重复。
                .distinct()
                .collect(Collectors.toList());
        //随机返回一个
        Random random=new Random();
        Integer pos=random.nextInt(positionList.size());
        return positionList.get(pos);
    }

    @Override
    public Hero getHeroByJob(String job) {
        //找到符合该职业的全部英雄
        List<Hero> positionList=this.heros.stream().filter(hero->{return hero.getHeroType().equals(job);}).collect(Collectors.toList());
        //随机返回一个
        //随机返回一个
        Random random=new Random();
        Integer pos=random.nextInt(positionList.size());
        return positionList.get(pos);
    }
}
